package org.nvm.dic;

import java.io.IOException;
import java.util.Collection;
import java.util.List;

import org.nvm.cfg.DictConfiguration;
import org.nvm.util.NVMUtils;
import org.nvm.util.ResourceReader;

public class Dictionary {

	private static Dictionary instance;

	/*
	 * 主词典对象
	 */
	private DictSegment _MainDict;
	
	/*
	 * 量词词典
	 */
	private DictSegment _QuantifierDict;
	/*
	 * 单字带词频词典
	 */
	private DictCharFrequencyNode _CharFreqDict;
	/*
	 * 配置对象
	 */
	private DictConfiguration cfg;
	
	private Dictionary(DictConfiguration configuration) {
		this.cfg = configuration;
		this._MainDict = new DictSegment((char)0);
		
		loadSystemDic(this._MainDict);
		
		loadQuantifierDic();
		
		loadCharFrequencyDic();
	}
	
	public static Dictionary initial(DictConfiguration configuration) {
		if(instance == null) {
			synchronized (Dictionary.class) {
				if(instance == null) {
					instance = new Dictionary(configuration);
				}
			}
		}
		
		return instance;
	}
	
	public static Dictionary reload(DictConfiguration configuration) {
		Dictionary newSingle = new Dictionary(configuration);
		if(newSingle != null) {
			instance = newSingle;
		}
		return instance;
	}
	
	public static Dictionary getInstance() {
		if(instance == null) {
			throw new IllegalStateException("please init dic first with method [Dictionary.initial(DictConfiguration configuration)]");
		}
		return instance;
	}
	
	public void addSegmentWords(Collection<String> words) {
		if(NVMUtils.isNotEmpty(words)) {
			for(String word : words) {
				addSegmentWord(word);
			}
		}
	}
	public void addSegmentWord(String word) {
		if(NVMUtils.isNotBlank(word)) {
			this._MainDict.fillSegment(word.trim().toLowerCase().toCharArray());
		}
	}
	public void removeSegmentWords(Collection<String> words) {
		if(NVMUtils.isNotEmpty(words)) {
			for(String word : words) {
				removeSegmentWord(word);
			}
		}
	}
	public void removeSegmentWord(String word) {
		if(NVMUtils.isNotBlank(word)) {
			this._MainDict.disableSegment(word.trim().toLowerCase().toCharArray());
		}
	}
	
	
	/**
	 * 检索匹配主词典
	 * @param charArray
	 * @return Hit 匹配结果描述
	 */
	public Hit matchInMainDict(char[] charArray){
		return instance._MainDict.matchCharArray(charArray);
	}
	
	/**
	 * 检索匹配主词典
	 * @param charArray
	 * @param begin
	 * @param length
	 * @return Hit 匹配结果描述
	 */
	public Hit matchInMainDict(char[] charArray , int begin, int length){
		return instance._MainDict.matchCharArray(charArray, begin, length);
	}
	
	/**
	 * 检索匹配量词词典
	 * @param charArray
	 * @param begin
	 * @param length
	 * @return Hit 匹配结果描述
	 */
	public Hit matchInQuantifierDict(char[] charArray , int begin, int length){
		return instance._QuantifierDict.matchCharArray(charArray, begin, length);
	}
	
	/**
	 * 从已匹配的Hit中直接取出DictSegment，继续向下匹配
	 * @param charArray
	 * @param currentIndex
	 * @param matchedHit
	 * @return Hit
	 */
	public Hit matchWithHit(char[] charArray , int currentIndex , Hit matchedHit){
		DictSegment ds = matchedHit.getMatchedDictSegment();
		return ds.matchCharArray(charArray, currentIndex, 1 , matchedHit);
	}
	
	
	private void loadQuantifierDic() {
		_QuantifierDict = new DictSegment((char)0);
		loadWordsToDictSegment(this.cfg.getQuantifierDicionary(), _QuantifierDict);
	}
	private void loadSystemDic(DictSegment dictSeg) {
		
		loadWordsToDictSegment(this.cfg.getMainDictionary(), dictSeg);
		
		loadWordsToDictSegment(this.cfg.getExtDictionarys(), dictSeg);
		
	}
	private void loadWordsToDictSegment(List<String> dictionaryFilePaths, DictSegment seg) {
		for(String filePath : dictionaryFilePaths) {
			loadWordsToDictSegment(filePath, seg);
		}
	}
	
	private void loadWordsToDictSegment(String dictionaryFilePath, DictSegment seg) {
		ResourceReader reader = null;
		try {
			reader = new ResourceReader(dictionaryFilePath);
			reader.loadByPath(dictionaryFilePath);
			
			String line = null;
			
			while((line = reader.readLine()) != null) {
				if(NVMUtils.isNotBlank(line) && line.charAt(0) != '#') {
					seg.fillSegment(line.trim().toLowerCase().toCharArray());
				}
			}
			
		} catch (Exception e) {
			System.err.println("loading word dic to segment error. file : " + dictionaryFilePath + ", class :" + seg.getClass().getName());
		} finally {
			if(reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	private void loadCharFrequencyDic() {
		ResourceReader reader = null;
		try {
			reader = new ResourceReader("/chars.dic");
			reader.loadByPath("/chars.dic");
			
			String line = null;
			this._CharFreqDict = new DictCharFrequencyNode();
			while((line = reader.readLine()) != null) {
				if(NVMUtils.isNotBlank(line) && line.charAt(0) != '#') {
					String[] vls = line.split("\\s+");
					if(vls.length == 2) {
						_CharFreqDict.addCharFrequency(vls[0].charAt(0), (float)Math.sqrt(Integer.parseInt(vls[1] + 1)));
					}
				}
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			System.err.println("loading char frequency dic error.");
		} finally {
			if(reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public float getCharFrequency(char ch) {
		return _CharFreqDict.getCharFrequency(ch);
	}
}
